package com.yyoa.controller;

import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.yyoa.model.Constraint;
import com.yyoa.model.ConstraintGroup;
import com.yyoa.model.Page;
import com.yyoa.model.SimpleConstraint;
import com.yyoa.util.ReflectionUtils;

@SuppressWarnings("rawtypes")
@Controller
public class BaseController {
	// logger日志对象
	protected Logger log = Logger.getLogger(this.getClass());

	/**
	 * 异常控制，这便是异常细节可控，将来可用于支持国际化（异常信息国际化）
	 */
	@ExceptionHandler(RuntimeException.class)
	@ResponseBody
	public Map<String, String> handleRuntTimeException(Exception ex, HttpServletRequest request) {
		log.error(ex.toString());
		String exceptionMessage = ex.getMessage();
		log.error(exceptionMessage);

		Map<String, String> errorMap = Maps.newHashMap();
		errorMap.put("error", exceptionMessage);
		return errorMap;
	}

	@ExceptionHandler(Exception.class)
	@ResponseStatus(value = HttpStatus.INTERNAL_SERVER_ERROR)
	@ResponseBody
	public Map<String, String> handleException(Exception ex, HttpServletRequest request) {
		log.error(ex.toString());
		String exceptionMessage = ex.getMessage();
		log.error(exceptionMessage);

		Map<String, String> errorMap = Maps.newHashMap();
		errorMap.put("error", exceptionMessage);
		return errorMap;
	}

	public Map<String, String> handleResonpse(String responseMessage) {
		Map<String, String> responseMessageMap = Maps.newHashMap();
		responseMessageMap.put("succeed", responseMessage);
		return responseMessageMap;
	}

	public Map<String, String> handleGotoPage(String page) {
		Map<String, String> gotoPage = Maps.newHashMap();
		gotoPage.put("goToPage", page);
		return gotoPage;
	}

	public Page initPage(HttpServletRequest httpRequest) {
		Page page = new Page();
		page.setPageSize(Integer.parseInt(httpRequest.getParameter("rows")));
		page.setPageNo(Integer.parseInt(httpRequest.getParameter("page")));
		page.setOrder(httpRequest.getParameter("sord"));
		return page;
	}

	public Constraint initConstraint(HttpServletRequest httpRequest, Class cla) {
		String search = httpRequest.getParameter("_search");
		if (StringUtils.isEmpty(search) || !Boolean.valueOf(search)) {
			return null;
		}

		JSONObject filtersObject = JSONObject.fromObject(httpRequest.getParameter("filters"));
		JSONArray rules = filtersObject.getJSONArray("rules");
		List<Constraint> constraints = Lists.newArrayList();
		for (Object obj : rules) {
			constraints.add(initSimpleConstraint((JSONObject) obj, cla));
		}

		String groupOp = filtersObject.getString("groupOp");
		if ("AND".equals(groupOp)) {
			return new ConstraintGroup(ConstraintGroup.LOGIC_AND, constraints);
		} else if ("OR".equals(groupOp)) {
			return new ConstraintGroup(ConstraintGroup.LOGIC_OR, constraints);
		} else {
			throw new IllegalStateException("compareGroup '" + groupOp + "' is not support yet");
		}
	}

	private SimpleConstraint initSimpleConstraint(JSONObject rule, Class cla) {
		String operator = tranOperator(rule.getString("op"));
		String fieldName = rule.getString("field");
		Class fieldClass = ReflectionUtils.getFieldType(cla, fieldName);
		if (String.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getString("data"));
		} else if (int.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getInt("data"));
		} else if (Integer.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getInt("data"));
		} else if (long.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getLong("data"));
		} else if (Long.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getLong("data"));
		} else if (boolean.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getBoolean("data"));
		} else if (Boolean.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getBoolean("data"));
		} else if (double.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getDouble("data"));
		} else if (Double.class.isAssignableFrom(fieldClass)) {
			return new SimpleConstraint(fieldName, operator, rule.getDouble("data"));
		} else {
			throw new IllegalStateException("initSimpleConstraint fail!");
		}
	}

	public static void main(String[] args) {
		System.out.println(Double.class.isAssignableFrom(Object.class));
	}

	private String tranOperator(String operator) {
		if ("eq".equals(operator)) {
			return SimpleConstraint.COMPARE_EQUAL;
		} else if ("ne".equals(operator)) {
			return SimpleConstraint.COMPARE_NOT_EQUAL;
		} else if ("gt".equals(operator)) {
			return SimpleConstraint.COMPARE_GREATER;
		} else if ("lt".equals(operator)) {
			return SimpleConstraint.COMPARE_SMALLER;
		} else if ("ge".equals(operator)) {
			return SimpleConstraint.COMPARE_GREATER_EQUAL;
		} else if ("le".equals(operator)) {
			return SimpleConstraint.COMPARE_SMALLER_EQUAL;
		} else if ("bw".equals(operator)) {
			return SimpleConstraint.COMPARE_LIKE_START;
		} else if ("bn".equals(operator)) {
			return SimpleConstraint.COMPARE_NOT_LIKE_START;
		} else if ("ew".equals(operator)) {
			return SimpleConstraint.COMPARE_LIKE_END;
		} else if ("en".equals(operator)) {
			return SimpleConstraint.COMPARE_NOT_LIKE_END;
		} else if ("cn".equals(operator)) {
			return SimpleConstraint.COMPARE_LIKE_ANYWHERE;
		} else if ("nc".equals(operator)) {
			return SimpleConstraint.COMPARE_NOT_LIKE_ANYWHERE;
		} else {
			throw new IllegalStateException("compareOperator '" + operator + "' is not support yet");
		}
	}
}
